package output;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import calendar.Calendar;
import calendar.Event;
import calendar.Timestamp;

/**
 * See also @Parser
 * @author Monika
 *
 */

public class N3FileParser extends Parser {

	private static final String CALENDAR_USERNAME_LABEL = ":cal_user";
	private static final String CALENDAR_PASSWORD_LABEL = ":cal_pass";
	private static final String CALENDAR_URL_LABEL = ":cal_url";
//  private static final String CALENDAR_START_INDICATOR = "############\n# CALENDAR #\n############";
//	private static final String CALENDAR_EVENTS_POSSIBLE_INDICATOR = "#####################\n# EVENTS - possible #\n#####################";
	
	public String getFilenamePattern() {
		return "p[0-9]+.n3";
	}

	public String getUserCalUrlFromFile(String filename) {
		String url = null;
		try {
			BufferedReader in = new BufferedReader(new FileReader(filename));			
			String line = in.readLine();
			while(line!=null&&url==null){
				
				int index = line.indexOf(CALENDAR_URL_LABEL);
				if (index>0){
					url = line.substring(index+CALENDAR_URL_LABEL.length());
					int inx = url.indexOf(":");										
					url = url.substring(inx+2,url.length()-2);
				}
				line = in.readLine();				
			}
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException ioe){
			ioe.printStackTrace();
		}			
		return url;
	}
	
	public void writeCalendarData(String filename, Calendar calendar, String outfilename) {		
		try{			
			
			this.out = new BufferedWriter(new FileWriter(outfilename));			
			BufferedReader in = new BufferedReader(new FileReader(filename));			
			String line = in.readLine();

			//'entity' and 'rule' - are just names invented by me, I don't know 
			//the proper naming ;)
			boolean entityStarted = false;
			boolean ruleStarted = false;
						
			String currentEntityStored=null;	
			List<String> currentEntityAttrsStored=null;
			
			String currentEntityType=null;
			boolean ignoreCurrentEntity=false;		
			boolean newEventsWritten=false; 			
												
			while(line!=null){
				String checkLine = line.trim();
				if (checkLine.contains("#")){//comment - rewrite
					writeLine(line);
					
				}else if(!ruleStarted&&checkLine.startsWith(":")){
					//if entity starts do not rewrite it immediately, but store.
					//At the end check if the type is a Possible Event
					//if yes, then ignore, if not, then rewrite all stored entity
					//to output file
					
					if (!entityStarted){
						entityStarted=true;						
						
						//if the previous entity was Calendar and new events were not written yet
						// - here's the time to write them (they will be inserted after any
						// comments, just before next entity)
						
						if ("Calendar".equals(currentEntityType)&&!newEventsWritten){
							writeNewEvents(calendar);			
							newEventsWritten=true;		
						}					
						
						ignoreCurrentEntity=false;
						currentEntityStored=line;//checkLine.substring(1);
						currentEntityAttrsStored = new ArrayList<String>();
												
					}else{//end of entity
						if (checkLine.endsWith(".")){
							entityStarted=false;
						}
						checkLine = checkLine.substring(0,checkLine.length()-1);
						String[] attrs = checkLine.split("\\s+");
											
						String type = attrs[0].substring(1);
						String value = attrs[1].substring(1);
						currentEntityAttrsStored.add(line);
						if("tense".equals(type)&&"Possible".equals(value)&&"Event".equals(currentEntityType)){
							ignoreCurrentEntity=true;			
						}
						
						if ("Calendar".equals(currentEntityType)
								&&"calendarID".equals(type)){
							calendar.setCalendarID(value);//set calendar ID
						}
																	
						if (!entityStarted){//then entity ended
							//rewrite all entity unless it is a Possible event
							if (!ignoreCurrentEntity){
								writeLine(currentEntityStored);
								for (String s: currentEntityAttrsStored){
									writeLine(s);
								}
							}															
						}						
												
					}
				}else if(!ruleStarted&&checkLine.startsWith("rdf:type")){
					
					String type = checkLine.substring(8,checkLine.length()-1).trim().substring(1);
					currentEntityType=type;
					currentEntityAttrsStored.add(line);

					//I am not sure if { and } means rule, anyway it is something we
					//do not want to care about
					
				}else if(!ruleStarted&&checkLine.startsWith("{")){
					ruleStarted=true;
					writeLine(line);
				}else if (ruleStarted&&checkLine.startsWith("}")){
					ruleStarted=false;
					writeLine(line);
				}else{
					writeLine(line);
				}								
				line = in.readLine();
			}									
			in.close();
			out.close();
		}catch(IOException ioe){
			ioe.printStackTrace();
		}
		
	}
	
	
	public void writeNewEvents(Calendar calendar) {
		writeLine("");
		
		/* target format:
		:event_2
			rdf:type	:Event;
			:calendarID	:c0001;
			:aspect		?;
			:tense		:Possible;
			:startDateTime	[:year 2009; :month 6; :day 13; :hour 16; :minute 0];
			:endDateTime	[:year 2009; :month 6; :day 13; :hour 17; :minute 0].

		 */
		
		int i = 1;
		for (Event e: calendar.getEvents()){			
			Timestamp t1 = e.getStartTime();
			Timestamp t2 = e.getEndTime();
			writeLine(":event_"+i+"cal");
			writeLine("\trdf:type\t:Event;");
			
			if (calendar.getCalendarID()==null) System.err.println("OOps calendar ID was not read - it is null!");
			
			writeLine("\t:calendarID\t:"+calendar.getCalendarID()+";");
			writeLine("\t:aspect\t:"+e.getEventTitle()+";");
			writeLine("\t:tense\t:Possible;");
			writeLine("\t:startDateTime	[:year "+t1.getYear()+"; :month "+t1.getMonth()+"; :day "+t1.getDay()+"; :hour "+t1.getHour()+"; :minute "+t1.getMinute()+"];");
			writeLine("\t:endDateTime	[:year "+t2.getYear()+"; :month "+t2.getMonth()+"; :day "+t2.getDay()+"; :hour "+t2.getHour()+"; :minute "+t2.getMinute()+"].");
			writeLine("");
			i++;
		}		
	}

}
